package com.yuandian.business.monitor.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.bpm.common.data.resolver.ParamResolver;
import com.yuandian.business.monitor.mapper.BusiAlarmTrendMapper;
import com.yuandian.business.monitor.service.IBusiAlarmTrendService;
import com.yuandian.api.business_monitor.vo.AlarmRatioListNodeExcelVO;
import com.yuandian.api.business_monitor.vo.AlarmRatioListTypeExcelVO;
import com.yuandian.api.business_monitor.vo.AlarmRatioListVO;
import com.yuandian.api.business_monitor.vo.AlarmTrendMapVO;
import com.yuandian.api.business_monitor.po.AlarmDistribteMapParams;
import com.yuandian.base.service.ITaskDataService;
import com.yuandian.utils.YDateUtil;
import com.yuandian.vo.TrendDataVo;
import com.yuandian.constant.ConfigKey;
import com.yuandian.exception.SqlTemplateException;
import com.yuandian.utils.PageDataInfo;
import com.yuandian.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 告警数据趋势
 *
 * @author zhoutian
 * @date 2020/9/24 11:23
 */
@Service
@Slf4j
public class BusiAlarmTrendServiceImpl implements IBusiAlarmTrendService {

	private static String TABLE_NAME_BUSINESS_ALARM = "dwd_business_alarm";


	@Autowired
	BusiAlarmTrendMapper busiAlarmTrendMapper;

	@Autowired
	private ITaskDataService taskDataService;

	/**
	 * 查询告警类型占比信息图
	 *
	 * @param params
	 * @return 趋势图VO
	 */
	@Override
	public Object[] queryAlarmRatioMap(AlarmDistribteMapParams params) throws ParseException {
		List<Object> source = new ArrayList<>();
		Date currentTime = YDateUtil.parse(params.getCurrentTime());
		//1.根据入参获取开始时间and结束时间。用于数据范围查询
		Map<String, String> dateMap = YDateUtil.getTimePiece(currentTime, 0, YDateUtil.getHour(new Date()));
		params.setStartTime(dateMap.get("startTime"));
		params.setEndTime(dateMap.get("endTime"));
		TrendDataVo trendDataVo = taskDataService.getTrendObject("系统告警趋势统计", params.getStartTime(), params.getEndTime(), null);
		if (trendDataVo.isLastShow()) {
			params.setEndTime(YDateUtil.parseDateToStr(YDateUtil.YYYY_MM_DD_HH_MM_SS, new Date(YDateUtil.parseDate(trendDataVo.getTrendEndTime()).getTime())));
			dateMap.put("endTime", params.getEndTime());
		}
		//2.查询数据
		List<AlarmTrendMapVO> data = busiAlarmTrendMapper.queryAlarmRatioMap(params);
		//3.数据不为空，则往下
		if (null != data) {
			Function<AlarmTrendMapVO, String> groupByColumn = AlarmTrendMapVO::getAlarmTypeName;
			source = dataConvert(data, groupByColumn, dateMap);
		}
		return source.toArray();
	}

	/**
	 * 查询节点占比告警图
	 *
	 * @param params 告警数据趋势查询统一参数
	 * @return 趋势图VO
	 */
	@Override
	public Object[] queryNodeRatioMap(AlarmDistribteMapParams params) throws ParseException {
		List<Object> source = new ArrayList<>();
		Date currentTime = YDateUtil.parseDate(params.getCurrentTime());
		String tableName = "ads_busi_alarm_trend_m";
		//1.根据入参获取开始时间and结束时间。用于数据范围查询
		Date date = new Date();
		Map<String, String> dateMap = YDateUtil.getTimePiece(currentTime, 0, YDateUtil.getHour(date), 0, YDateUtil.getMinute(date), 0, 0);
		params.setStartTime(dateMap.get("startTime"));
		params.setEndTime(dateMap.get("endTime"));
		TrendDataVo trendDataVo = taskDataService.getTrendObject("系统告警趋势统计", params.getStartTime(), params.getEndTime(), null);
		if (trendDataVo.isLastShow()) {
			params.setEndTime(YDateUtil.parseDateToStr(YDateUtil.YYYY_MM_DD_HH_MM_SS, new Date(YDateUtil.parseDate(trendDataVo.getTrendEndTime()).getTime())));
			dateMap.put("endTime", params.getEndTime());
		}
		//查询服务器响应超时告警信息
		List<AlarmTrendMapVO> data = busiAlarmTrendMapper.queryNodeRatioMap(params, tableName);
		//2.数据不为空，则往下
		if (null != data) {
			Function<AlarmTrendMapVO, String> groupByColumn = AlarmTrendMapVO::getSegmentName;
			source = dataConvert(data, groupByColumn, dateMap);
		}
		return source.toArray();
	}

	/**
	 * 访问量告警分类详情列表：之前是差es，现在改差doris
	 *
	 * @param params
	 * @return
	 */
	@Override
	public PageDataInfo queryTypeProportion(AlarmDistribteMapParams params) {
		List<AlarmRatioListVO> list = new ArrayList<>();
		Date labelTime = YDateUtil.dateTime(YDateUtil.YYYY_MM_DD_HH_MM_SS, params.getCurrentTime());
		//1.表名
		Date date = new Date();
		Map<String, String> dateMap = YDateUtil.getTimePiece(labelTime, 0, YDateUtil.getHour(date), 0, YDateUtil.getMinute(date), 0, 0);
		params.setStartTime(dateMap.get("startTime"));
		params.setEndTime(dateMap.get("endTime"));
		IPage page = new Page(params.getPageNum(), params.getPageSize());
		//毫秒值
		list = busiAlarmTrendMapper.queryAlarmTypeDetail(page, params);
		page.setRecords(list);
		return new PageDataInfo(page.getTotal(), list);

	}

	/**
	 * 访问量告警分类网端详情列表
	 *
	 * @param params
	 * @return
	 */
	@Override
	public PageDataInfo queryNodeProportion(AlarmDistribteMapParams params) {
		List<AlarmRatioListVO> list = new ArrayList<>();
		IPage page = new Page(params.getPageNum(), params.getPageSize());
		long totalHits = 0;
		try {
			Date labelTime = YDateUtil.dateTime(YDateUtil.YYYY_MM_DD_HH_MM_SS, params.getCurrentTime());
			String tableNameSuffix = YDateUtil.parseDateToStr(YDateUtil.YYYYMMDD, labelTime);
			Map<String, String> dateMap = YDateUtil.getTimePiece(labelTime, 0, 23);
			//毫秒值
			Long star = YDateUtil.getUsecFromDateStr(dateMap.get("startTime")) / 1000;
			Long end = YDateUtil.getUsecFromDateStr(dateMap.get("endTime")) / 1000;
			list = busiAlarmTrendMapper.queryNodeProportion(page, params, star, end);
			page.setRecords(list);
		} catch (Exception e) {

			throw new SqlTemplateException("网端详情列表查询错误！");
		}
		return new PageDataInfo(page.getTotal(), list);
	}

	/**
	 * 导出
	 *
	 * @param params   查询参数
	 * @param response HttpServletResponse
	 */
	@Override
	public void export(AlarmDistribteMapParams params, HttpServletResponse response) {
		params.setPageSize(1000000);
		try {
			if ("type".equals(params.getExportType())) {
				ExcelUtil.writeExcel(AlarmRatioListTypeExcelVO.class, "类型占比列表", "类型占比列表",
						queryTypeProportionForExport(params), response);
			} else {
				ExcelUtil.writeExcel(AlarmRatioListNodeExcelVO.class, "节点占比列表", "节点占比列表",
						queryNodeProportionForExport(params), response);
			}
		} catch (IOException e) {
			throw new SqlTemplateException("访问告警分布图列表下载报错！");
		}
	}

	/**
	 * 结果集转换并补全
	 *
	 * @param data          数据
	 * @param groupByColumn 分组字段
	 * @return List<Object>
	 */
	private List<Object> dataConvert(List<AlarmTrendMapVO> data, Function<AlarmTrendMapVO, String> groupByColumn, Map<String, String> dateMap) {
		SimpleDateFormat hourSdf = new SimpleDateFormat(YDateUtil.HH_MM);
		//获取配置信息
		int labelTimeLength = 10;
		try {
			labelTimeLength = Integer.parseInt(ParamResolver.getStr(ConfigKey.SYS_CONFIG_KEY + ConfigKey.SYS_LABLETIME_LENGTH, "10"));
			log.info("获取到配置刻度：{}", labelTimeLength);
		}catch (Exception e){
			log.error("获取刻度配置异常，异常原因：{}",e.getMessage());
		}

		//初始化刻度
		List<String> times = null;
		times = YDateUtil.splitDate("mm", labelTimeLength, YDateUtil.parseDate(dateMap.get("startTime")),
				YDateUtil.stringFormatDate(dateMap.get("endTime")), true, YDateUtil.HH_MM);

		Map<String, Integer> toMap = new LinkedHashMap<>();
		//刻度补全
		for (String time : times) {
			toMap.put(time, 0);
		}
		List<Object> source = new ArrayList<>(20);
		/* 2.开始转换结果集 */
		data.stream().collect(Collectors.groupingBy(groupByColumn)).forEach((name, list) -> {
			//刻度对应值
			List<Object> dataValue = new ArrayList<>();
			//抬头
			dataValue.add(name);
			//2.1初步转换
			toMap.entrySet().stream().filter(na -> na.getValue() > 0).forEach(m -> toMap.put(m.getKey(), 0));
			for (AlarmTrendMapVO vo : list) {
				toMap.put(hourSdf.format(vo.getLabelTime()), vo.getAlarmTotalSum() == null ? 0 : vo.getAlarmTotalSum());
			}
			dataValue.addAll(toMap.values());
			//插入对象信息
			dataValue.add(list.get(0));
			//插入结果集value
			source.add(dataValue);
			//最大展示10个类型
			if (source.size() > 10) {
				return;
			}
		});
		times.add(0, "labelTime");
		source.add(0, times);
		return source;
	}

	/**
	 * 类型占比导出查询
	 *
	 * @param params
	 * @return
	 */
	public List<AlarmRatioListTypeExcelVO> queryTypeProportionForExport(AlarmDistribteMapParams params) {
		List<AlarmRatioListVO> list = new ArrayList<>();
		Date labelTime = YDateUtil.dateTime(YDateUtil.YYYY_MM_DD_HH_MM_SS, params.getCurrentTime());
		//1.表名
		String[] tableName = {TABLE_NAME_BUSINESS_ALARM};
		Date date = new Date();
		Map<String, String> dateMap = YDateUtil.getTimePiece(labelTime, 0, YDateUtil.getHour(date), 0, YDateUtil.getMinute(date), 0, 0);
		params.setStartTime(dateMap.get("startTime"));
		params.setEndTime(dateMap.get("endTime"));
		list = busiAlarmTrendMapper.queryAlarmTypeDetail(params);
		return BeanUtil.copyToList(list, AlarmRatioListTypeExcelVO.class);

	}

	/**
	 * 节点占比导出查询
	 *
	 * @param params
	 * @return
	 */
	public List<AlarmRatioListNodeExcelVO> queryNodeProportionForExport(AlarmDistribteMapParams params) {
		List<AlarmRatioListVO> list = new ArrayList<>();
		try {
			Date labelTime = YDateUtil.dateTime(YDateUtil.YYYY_MM_DD_HH_MM_SS, params.getCurrentTime());
			Map<String, String> dateMap = YDateUtil.getTimePiece(labelTime, 0, 23);
			//毫秒值
			Long star = YDateUtil.getUsecFromDateStr(dateMap.get("startTime")) / 1000;
			Long end = YDateUtil.getUsecFromDateStr(dateMap.get("endTime")) / 1000;

			list = busiAlarmTrendMapper.queryNodeProportion(params, star, end);
		} catch (Exception e) {

			throw new SqlTemplateException("网端详情列表查询错误！");
		}
		return BeanUtil.copyToList(list, AlarmRatioListNodeExcelVO.class);
	}
}
